package node;

import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.geometry.Primitive;
import component.AbstractComponent;
import component.Status;

abstract public class GeoNode extends BranchGroup {
	
	private static int DEBUG_COUNTER = 0;
	protected final int DEBUG_ID;
	
	private final Point3d position = new Point3d();
	
	private TransformGroup translationGroup = new TransformGroup();

	private Appearance appearance;
	
	private AbstractComponent component;
	
	public GeoNode(AbstractComponent component, Tuple3d position, int status) {
		super();
		this.DEBUG_ID = DEBUG_COUNTER++;
		
		this.setCapability(ALLOW_DETACH);
		this.setCapability(ENABLE_PICK_REPORTING);
		this.addChild(translationGroup);
	
	  
		translationGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		translationGroup.setCapability(TransformGroup.ALLOW_LOCAL_TO_VWORLD_READ);

		this.setPos(position);
	
		this.component = component;
		this.setStatus(new Status(status));
	}
	
	public AbstractComponent getComponent() {
		return this.component;
	}
	
	public Point3d getPos() {
		return new Point3d(position);
	}
	
	public void setPos(Tuple3d position) {
		this.position.set(position);
		this.updateTranslation();
	}
	
	private void setAppearance(Appearance appearance) {
		this.appearance = appearance;
		if (this.getPrimitive() != null) this.getPrimitive().setAppearance(appearance);
	}
	
	protected Appearance getAppearance() {
		return appearance;
	}
	
	protected void updateTranslation() {
		Transform3D transform = new Transform3D();
		transform.set(new Vector3d(position));
		translationGroup.setTransform(transform);		
	}
	
	protected TransformGroup getTranslationGroup() {
		return translationGroup;
	}
	
	
	abstract public PickShape getPickShape();
	
	abstract protected Primitive getPrimitive();

	public boolean intersect(GeoNode other) {
		if (this == other) return false;
		
		SceneGraphPath scenePath = other.getSceneGraphPath();
		
		PickShape pickShape = this.getPickShape();
		Shape3D testShape = (Shape3D) scenePath.getObject();

		return testShape.intersect(scenePath, pickShape);
	}
	
	
	abstract public SceneGraphPath getSceneGraphPath();

	public void setStatus(Status status) {
		this.setAppearance(status.getAppearance(this.getComponent()));
	}
	
	public String debugInfo() {
		String debug = String.format("[%s: %s]",
				this.toString(),
				this.isLive() ? "LIVE " : "");		
		return debug;
	}
	
}
